package jdbcForMe.mySetting;

import jdbcForMe.setting.FormSetting;
import jdbcForMe.setting.ItemSetting;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MyFormSetting implements FormSetting {
    private Node head;
    private Node tail;
    private int size;
    private Node iterateNode;

    public MyFormSetting() {
    }

    private boolean isEmpty() {
        return head == null;
    }

    public MyFormSetting(ItemSetting is) {
        Node node = new Node(null, is, null);
        size++;
        head = node;
        tail = node;
        iterateNode = head;
    }

    /**
     * 增加元素
     *
     * @param is
     */
    public void mix(ItemSetting is) {
        if (isEmpty()) {
            Node node = new Node(null, is, null);
            head = node;
            tail = node;
            iterateNode = head;
            node = null;
        } else {
            Node newNode = new Node(tail, is, null);
            tail.setNext(newNode);
            tail = newNode;
            newNode = null;
        }
        size++;
    }

    /**
     * 删除元素
     *
     * @param is 需要删除的元素
     */
    public void delete(ItemSetting is) {
        if (isEmpty()) return;
        Node nextNode = getNode(is);
        if (nextNode != null) {
            if (nextNode == head) {
                deleteHead();
            } else if (nextNode == tail) {
                deleteTail();
            } else {
                deleteMidContent(nextNode);
            }
            size--;
        }
    }

    /**
     * 删除头节点（private）
     */
    private void deleteHead() {
        if (head.getNext() != null) {
            Node temp = head;
            temp.getNext().setPrev(null);
            head = temp.getNext();
            temp = null;
        } else {
            dispose();
        }
    }

    /**
     * 删除尾节点（private）
     */
    private void deleteTail() {
        if (tail.getPrev() != null) {
            Node temp = tail;
            temp.getPrev().setNext(null);
            tail = temp.getPrev();
            temp = null;
        } else {
            dispose();
        }
    }

    /**
     * 删除中间节点（private）
     */
    private void deleteMidContent(Node temp) {
        Node oldNode = temp.getPrev();
        temp.getNext().setPrev(oldNode);
        oldNode.setNext(temp.getNext());
        temp = null;
    }

    /**
     * 遍历寻找节点（private）
     */
    private Node getNode(ItemSetting is) {
        //添加异常
        if (isEmpty()) return null;
        Node nextNode = head;
        //        //if (nextNode == null) return null;
        while (nextNode != null) {
            if (nextNode.getContent().compareToSom(is)) {
                return nextNode;
            }
            nextNode = nextNode.getNext();
        }
        return null;
    }

    /**
     * 修改数据表
     *
     * @param is     需要修改值的ItemSetting对象
     * @param keys   所需要修改的属性（必须与ItemSetting的属性名一样）
     * @param values 所替换的值（赋值顺序必须与keys的顺序一样）
     */
    public void modify(ItemSetting is, String[] keys, String[] values) {
        if (isEmpty()) return;
        Node node = getNode(is);
        if (node == null) return;
        if (keys.length != values.length) return;
        for (int i = 0; i < keys.length; i++) {
            try {
                Method method = is.getClass().getMethod(getOrSet("set", keys[i]), String.class);
                method.invoke(is, values[i]);
            } catch (NoSuchMethodException e) {
                System.out.println("出现了找不到方法Setter异常");
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                System.out.println("出现了非法权限异常");
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                System.out.println("底层的方法出现错误");
                e.printStackTrace();
            }
        }
    }

    /**
     * 产生Getter的名字或者Setter的名字
     *
     * @param prefix "get" or "set"
     * @param suffix 后缀
     * @return 返回产生的字符串
     */
    private String getOrSet(String prefix, String suffix) {
        StringBuilder sb = new StringBuilder(suffix);
        sb.setCharAt(0, (char) (sb.codePointAt(0) - 32));
        return prefix + sb.toString();
    }

    /**
     * 查询指定的一条数据
     *
     * @param is 需要查询的ItemSetting
     * @return 返回一个ItemSetting对象，没有则返回null
     */
    public ItemSetting select(ItemSetting is) {
        //添加异常
        if (isEmpty()) return null;
        Node node = getNode(is);
        if (node != null) {
            return node.getContent();
        }
        return null;
    }

    /**
     * 查询数据表中的全部数据
     *
     * @return 返回一个ItemSetting数组
     */
    public ItemSetting[] select() {
        //添加异常
        if (isEmpty()) return null;
        ItemSetting[] iss = new ItemSetting[size];
        Node node = head;
        for (int i = 0; i < iss.length; i++) {
            iss[i] = node.getContent();
            node = node.getNext();
        }
        return iss;
    }

    /**
     * 释放数据表
     */
    public void dispose() {
        head = null;
        tail = null;
        size = 0;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Node temp = head;
        while (temp != null) {
            sb.append(temp.content.toString() + "\n");
            temp = temp.getNext();
        }
        return sb.toString();
    }

    public boolean hasNext(){
        if (isEmpty()) return false;
        return iterateNode != null ;
    }

    public ItemSetting next(){
        Node temp = iterateNode;
        iterateNode = iterateNode.getNext();
        return temp.getContent();
    }

    public boolean update(){
        iterateNode = head;
        return false;
    }

    //Node
    private class Node {
        private Node prev;
        private ItemSetting content;
        private Node next;

        public Node() {
            prev = null;
            content = null;
            next = null;
        }

        public Node(Node prev, ItemSetting content, Node next) {
            this.prev = prev;
            this.content = content;
            this.next = next;
        }

        public Node getPrev() {
            return prev;
        }

        public void setPrev(Node prev) {
            this.prev = prev;
        }

        public ItemSetting getContent() {
            return content;
        }

        public void setContent(ItemSetting content) {
            this.content = content;
        }

        public Node getNext() {
            return next;
        }

        public void setNext(Node next) {
            this.next = next;
        }
    }
}
